package com.zb.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zb.entity.ZjAddress;
import com.zb.mapper.ZjAddressMapper;
import com.zb.service.ZjAddressService;
import com.zb.vo.Address;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author WEN
 * @since 2023-08-11
 */
@Service
public class ZjAddressServiceImpl extends ServiceImpl<ZjAddressMapper, ZjAddress> implements ZjAddressService {
    private static final String ADDRESS = "address:";
    private static final String CHILD_ADDRESS = ADDRESS + ":child-address:";

    @Resource
    private ZjAddressMapper addressMapper;
    @Resource
    private RedisTemplate redisTemplate;

    // 获取一级地址
    @Override
    public List<Address> getAddress() {
        if (hasAddress()) {
            return getAddressFromRedis();
        }
        List<ZjAddress> address = addressMapper.getAddress();
        List<Address> addrList = address.stream().filter(f -> f.getParentId() == 0).map(addr -> {
            return new Address(addr.getCode(), addr.getName(),
                    getChhildAddr(addr.getId(), address)
                    );
        }).toList();
        cache(ADDRESS, addrList);
        return addrList;
    }

    private List<Address> getChhildAddr(Long id, List<ZjAddress> address) {
        return address.stream().filter(f -> Objects.equals(id, f.getParentId())).map(addr -> {
            return new Address(addr.getCode(), addr.getName(),
                    getChhildAddr(addr.getId(), address)
            );
        }).toList();
    }

    // 获取子级地址
    @Override
    public List<Address> getChildAddress(String parentId) {
        if (hasChildAddress(parentId)) {
            return getChildAddressFromRedis(parentId);
        }
        List<Address> address = getAddress(parentId);
        return address;
    }

    /**
     * 缓存数据
     * @param k 数据键
     * @param data 数据
     * @return
     */
    private void cache(String k, Object data) {
        redisTemplate.opsForValue().set(k, data, 30, TimeUnit.DAYS);
    }

    private boolean hasAddress() {
        return Boolean.TRUE.equals(getAddressRedisKey());
    }

    private List<Address> getAddressFromRedis() {
        return  (List<Address>) redisTemplate.opsForValue().get(getAddressRedisKey());
    }

    private boolean hasChildAddress(String parentId) {
        return Boolean.TRUE.equals(getChildAddressRedisKey(parentId));
    }

    private List<Address> getChildAddressFromRedis(String parentId) {
        return  (List<Address>) redisTemplate.opsForValue().get(getChildAddressRedisKey(parentId));
    }

    private String getAddressRedisKey() {
        return ADDRESS;
    }

    private String getChildAddressRedisKey(String parentId) {
        return CHILD_ADDRESS + parentId;
    }

    private List<Address> getAddress(String parentId) {
        QueryWrapper<ZjAddress> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_id", parentId);
        List<ZjAddress> addressList = this.list(wrapper);

        List<Address> addrs = new ArrayList<>();
        addressList.forEach(t -> addrs.add(new Address(t.getId().toString(), t.getName())));
        return addrs;
    }
}
